package com.jd.risk.bankorder.util.file;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
 * 用于在配置文件以及数据之间进行转换的类
 * 
 * @author Liu Even
 */
public class DataBuilder {


    /**
     * 使用配置文件创建 2007 excel file
     * 
     * @param configs
     * @param type
     * @param colClass
     * @return
     */
    public static Workbook buildXSSFWorkbook(Collection<Map<String, Object>> configs, String type,
            Class<? extends Enum<? extends BasicConfigColumns>> colClass) {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet(type);
        // 创建第一行
        Row header = sheet.createRow(0);
        for (int headIndex = 0; headIndex < colClass.getEnumConstants().length; headIndex++) {
            Cell headerCell = header.createCell(headIndex, Cell.CELL_TYPE_STRING);
            headerCell.setCellValue(getConfigName(colClass.getEnumConstants()[headIndex]));
        }
        //设置配置数据
        Iterator<Map<String, Object>> iterator = configs.iterator();
        for (int dataIndex = 0; dataIndex < configs.size(); dataIndex++) {
            Map<String, Object> dataRow = iterator.next();
            Row body = sheet.createRow(dataIndex + 1);
            for (int bodyIndex = 0; bodyIndex < colClass.getEnumConstants().length; bodyIndex++) {
                Cell bodyCell = body.createCell(bodyIndex);
                Object valueObject = dataRow.get(getConfigName(colClass.getEnumConstants()[bodyIndex]));
                bodyCell.setCellValue(valueObject == null ? null : valueObject.toString());
            }
        }
        return workbook;
    }
    


    /**
     * 从配合文件中读取普通配置 get the value body list
     * 
     * @param workbook
     * @return
     * @see [相关类/方法](可选)
     * @since [产品/模块版本](可选)
     */
    public static Collection<Map<String, Object>> getObjectValue(Workbook workbook) {
        LinkedList<String> headList;
        Sheet sheet = workbook.getSheetAt(0);
        int index = 0;
        int length = sheet.getPhysicalNumberOfRows();
        Row row = sheet.getRow(index);
        headList = getHeadList(row);
        Collection<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
        index++;
        for (; index < length; index++) {
            Row currentRow = sheet.getRow(index);
            Map<String, Object> currentMap = getValueRow(headList, currentRow);
            if(currentMap != null){
                result.add(currentMap);
            }
        }
        return result;
    }

    /**
     * 获取一行的配置数据 the method will return a map which represents a row of data in excel file the every entity in the map
     * means a cell of a row, the key is the header matched with this cell and the value is the cell's real value
     * 
     * @param heads is the headers of the excel file
     * @param row is the current row to get value from
     * @return
     */
    private static Map<String, Object> getValueRow(LinkedList<String> heads, Row row) {
        Map<String, Object> map = new HashMap<String, Object>();
        int index = 0;
        int length = row.getLastCellNum();
        for (; index < length; index++) {
            Cell cell = row.getCell(index);
            Object currentValue = getCellValue(cell);
            if(index <heads.size())
              map.put(heads.get(index), currentValue);
        }
        return map;
    }


    /**
     * 获取普通配置的表头 all columns are treat as head
     * 
     * @param row
     * @return
     */
    private static LinkedList<String> getHeadList(Row row) {
        int index = 0;
        LinkedList<String> result = new LinkedList<String>();
        int length = row.getPhysicalNumberOfCells();
        for (; index < length; index++) {
            Cell cell = row.getCell(index);
            if (cell.getCellType() == Cell.CELL_TYPE_STRING) {
                result.add(cell.getStringCellValue());
            }
        }
        return result;
    }

    /**
     * 获取excel一个cell的value 
     * values of StringType is trimed
     * @param cell
     * @return
     */
    private static Object getCellValue(Cell cell) {
        Object result = null;
        // number format
        // DecimalFormat df = new DecimalFormat("0.00");
        if (cell == null) {
            return null;
        }
        int type = cell.getCellType();
        switch (type) {
            case Cell.CELL_TYPE_STRING:
                String rawValue = cell.getStringCellValue();
                result = rawValue==null?null:rawValue.trim();
                break;
            case Cell.CELL_TYPE_FORMULA:
                result = getFormulaCellValue(cell);
                break;
            case Cell.CELL_TYPE_BOOLEAN:
                result = cell.getBooleanCellValue();
                break;
            case Cell.CELL_TYPE_NUMERIC:
                if (HSSFDateUtil.isCellDateFormatted(cell)) {
                    result = cell.getDateCellValue();
                }else {
                    result = cell.getNumericCellValue();
                }
                
                break;
            default:
                break;
        }
        return result;
    }

    /**
     * 获取公式类型的cell的取值 get the cell value whose type is formula
     * 
     * @param cell
     * @return
     */
    private static String getFormulaCellValue(Cell cell) {
        String value;
        try {
            value = String.valueOf(cell.getNumericCellValue());
        } catch (IllegalStateException e) {
            value = String.valueOf(cell.getRichStringCellValue());
        }
        return value;
    }

    /**
     * 从配置的类中读取本配置文件的配置字段
     * 
     * @param column
     * @return
     * @see BasicConfigColumns
     */
    private static String getConfigName(Enum<?> column) {
        return ((BasicConfigColumns) column).getConfigName();
    }

}
